use std::os::windows::io::RawHandle;
use std::{
    ffi::{CString, c_char},
    fs::File,
    io::{self, Read},
    os::windows::io::FromRawHandle,
    thread,
    time::Duration,
};
use windows_sys::Win32::Foundation::{
    DUPLICATE_SAME_ACCESS, DuplicateHandle, HANDLE, INVALID_HANDLE_VALUE,
};
use windows_sys::Win32::Security::SECURITY_ATTRIBUTES;
use windows_sys::Win32::System::Console::{STD_ERROR_HANDLE, STD_OUTPUT_HANDLE, SetStdHandle};
use windows_sys::Win32::System::Threading::GetCurrentProcess;
use windows_sys::core::BOOL;

#[link(name = "kernel32")]
unsafe extern "system" {
    pub fn CreatePipe(
        hReadPipe: *mut HANDLE,
        hWritePipe: *mut HANDLE,
        lpPipeAttributes: *mut SECURITY_ATTRIBUTES,
        nSize: u32,
    ) -> BOOL;
}

unsafe extern "C" {
    fn ffmpeg_main(cmdline_str: *const c_char, argc: i32, argv: *const *const c_char) -> i32;
    fn ffmpeg_stop();
}

fn main() {
    println!("🚀 启动 Rust + FFmpeg");

    let (read_pipe, write_pipe) = create_pipe_and_redirect_stdout().expect("创建管道失败");

    // duplicate handle in main thread
    let mut dup_read: HANDLE = INVALID_HANDLE_VALUE;
    let success = unsafe {
        DuplicateHandle(
            GetCurrentProcess(),
            read_pipe,
            GetCurrentProcess(),
            &mut dup_read,
            0,
            0,
            DUPLICATE_SAME_ACCESS,
        )
    };
    if success == 0 {
        panic!("❌ DuplicateHandle 失败");
    }

    // ✅ cast to isize, move safely into thread
    let dup_read = dup_read as isize;

    let reader_thread = thread::spawn(move || unsafe {
        let mut file = File::from_raw_handle(dup_read as RawHandle);
        let mut buffer = [0u8; 1024];
        loop {
            match file.read(&mut buffer) {
                Ok(0) => break,
                Ok(n) => print!("reader---------->{}", String::from_utf8_lossy(&buffer[..n])),
                Err(e) => {
                    eprintln!("读取失败: {:?}", e);
                    break;
                }
            }
        }
    });

    // 启动 FFmpeg 主线程
    let ffmpeg_thread = thread::spawn(|| {
        test_record10();
        println!("✅  test_record10(); 完成");
    });

    ffmpeg_thread.join().unwrap();
    println!("✅  test_record10() JOIN 完成");

    // ✅ 关闭写端，通知读取线程 EOF
    unsafe {
        windows_sys::Win32::Foundation::CloseHandle(write_pipe);
    }


    reader_thread.join().unwrap();
    println!("✅ FFmpeg 完成");
}

fn test_record10() {
    let args = vec![
        "ffmpeg",
        "-loglevel",
        "info",
        "-y",
        "-f",
        "gdigrab",
        "-i",
        "desktop",
        "-r",
        "10",
        "-t",
        "10",
        "-fs",
        "100M",
        "-b:v",
        "1M",
        "test.mp4",
    ];

    let cstrings: Vec<CString> = args.iter().map(|s| CString::new(*s).unwrap()).collect();
    let argv: Vec<*const c_char> = cstrings.iter().map(|cs| cs.as_ptr()).collect();
    let cmdline_str = CString::new(args.join(" ")).unwrap();

    // 停止 FFmpeg
    let stopper = thread::spawn(|| {
        thread::sleep(Duration::from_secs(10));
        println!("🛑 10 秒到了，调用 ffmpeg_stop()");
        unsafe {
            ffmpeg_stop();
        }
    });

    unsafe {
        ffmpeg_main(cmdline_str.as_ptr(), argv.len() as i32, argv.as_ptr());
    }

    stopper.join().unwrap();
}

fn create_pipe_and_redirect_stdout() -> io::Result<(HANDLE, HANDLE)> {
    unsafe {
        let mut read_pipe: HANDLE = std::ptr::null_mut();
        let mut write_pipe: HANDLE = std::ptr::null_mut();

        let mut sa = SECURITY_ATTRIBUTES {
            nLength: std::mem::size_of::<SECURITY_ATTRIBUTES>() as u32,
            lpSecurityDescriptor: std::ptr::null_mut(),
            bInheritHandle: 1, // TRUE
        };

        let result = CreatePipe(&mut read_pipe, &mut write_pipe, &mut sa, 0);
        if result == 0 {
            return Err(io::Error::last_os_error());
        }
        

        // 设置 stderr 为 write_pipe
        if SetStdHandle(STD_ERROR_HANDLE, write_pipe) == 0 {
        //if SetStdHandle(STD_OUTPUT_HANDLE, write_pipe) == 0 {
            return Err(io::Error::last_os_error());
        }

        Ok((read_pipe, write_pipe))
    }
}
